package jpush

import (
	"errors"
	"fmt"

	. "go-share/models"
	"go-share/models/common"

	"github.com/DeanThompson/jpush-api-go-client"
	"github.com/DeanThompson/jpush-api-go-client/device"
	"github.com/DeanThompson/jpush-api-go-client/push"
)

var (
	client *jpush.JPushClient
)

var ErrClientIsNil = errors.New("[JPush] Client is nil")

type PushTarget struct {
	Alias       []string
	Tags        []string
	RegisterIDs []string
}

type UnityParams struct {
	MemberID   int64
	SubChannel int64
}

type UnityTarget struct {
	MemberID   int64         // 成员ID
	MemberIds  []interface{} // 成员ID串
	IsNoCache  bool          // 非缓存数据标记
	TargetID   int64         // 目标ID
	TargetType int           // 目标类型
}

type RegInfo struct {
	Param          UnityParams
	RegistrationID string
}

type RegInfos struct {
	Params          []UnityParams
	RegistrationIds []string
}

func New(appKey string, secret string) {
	if client == nil {
		client = jpush.NewJPushClient(appKey, secret)
	}

	// 如果是调试模式会输出日志
	client.SetDebug(true)
}

// 推送消息
// target:	接收对象（群组）
// alert:	提示文字
// extras:	业务字段
// mode:	推送生产环境标记
func Push(target PushTarget, alert string, title string, extras map[string]interface{}, mode bool) error {

	// 创建 Platform 对象
	platform := push.NewPlatform()

	// 支持所有平台
	platform.All()

	audience := push.NewAudience()
	if len(target.RegisterIDs) > 0 {
		audience.SetRegistrationId(target.RegisterIDs)
	}
	if len(target.Alias) > 0 {
		audience.SetAlias(target.Alias)
	}

	if len(target.Tags) > 0 {
		audience.SetTag(target.Tags)
	}

	r := []rune(alert)
	if len(r) > 40 {
		alert = string(r[:40]) + "..."
	}

	// Android 参数
	androidNotification := push.NewAndroidNotification(alert)
	androidNotification.Title = title
	androidNotification.Extras = extras

	// iOS 参数
	iosNotification := push.NewIosNotification(alert)
	iosNotification.Badge = "+1"
	iosNotification.Extras = extras
	iosNotification.Sound = "default"

	// message
	message := push.NewMessage(alert)
	message.Title = title
	message.Extras = extras

	// 创建 Options 对象
	// option 对象，表示推送可选项
	options := push.NewOptions()

	// iOS 平台，是否推送生产环境，false 表示开发环境；如果不指定，就是生产环境
	if mode {
		options.ApnsProduction = true
	} else {
		options.ApnsProduction = false
	}

	options.TimeToLive = 0
	// options.BigPushDuration = 1500

	// 初始化 Notification 对象
	notification := push.NewNotification(alert)
	notification.Ios = iosNotification
	notification.Android = androidNotification

	// 创建 PushObject 对象
	payload := push.NewPushObject()
	payload.Audience = audience
	payload.Notification = notification
	payload.Message = message
	payload.Options = options
	payload.Platform = platform

	// 推送
	_, err := client.Push(payload)

	return err
}

// --------------------------------------------------------------------------------

// 添加标签
func AddTags(registrationId string, tags ...string) error {
	if client == nil {
		return ErrClientIsNil
	}

	update := device.NewDeviceUpdate()
	update.AddTags(tags...)
	_, err := client.UpdateDevice(registrationId, update)
	return err
}

// 批量添加标签
func BatchAddTagUsers(tag string, registrationIds ...string) error {
	if client == nil {
		return ErrClientIsNil
	}

	args := device.NewUpdateTagUsersArgs()
	args.AddRegistrationIds(registrationIds...)
	_, err := client.UpdateTagUsers(tag, args)
	return err
}

// 批量删除标签
func BatchRemoveTagUsers(tag string, registrationIds ...string) error {
	if client == nil {
		return ErrClientIsNil
	}

	args := device.NewUpdateTagUsersArgs()
	args.RemoveRegistrationIds(registrationIds...)
	_, err := client.UpdateTagUsers(tag, args)
	return err
}

// 清除全部标签
func ClearAllTags(registrationId string) error {
	if client == nil {
		return ErrClientIsNil
	}

	update := device.NewDeviceUpdate()
	update.ClearAllTags()
	_, err := client.UpdateDevice(registrationId, update)
	return err
}

// 删除标签
func RemoveTags(registrationId string, tags ...string) error {
	if client == nil {
		return ErrClientIsNil
	}

	update := device.NewDeviceUpdate()
	update.RemoveTags(tags...)
	_, err := client.UpdateDevice(registrationId, update)
	return err
}

// --------------------------------------------------------------------------------

// 添加成员标签
func AddMemberTag(target UnityTarget) error {
	info, err := getRegistrationInfo(target)
	if err != nil {
		return err
	}

	tag := fmt.Sprintf(JPUSH_TAG_MEMBER, IDEncrypt(target.TargetID))

	return AddTags(info.RegistrationID, tag)
}

// 移除成员标签
func RemoveMemberTag(target UnityTarget) error {
	info, err := getRegistrationInfo(target)
	if err != nil {
		return err
	}

	tag := fmt.Sprintf(JPUSH_TAG_MEMBER, IDEncrypt(target.TargetID))

	return RemoveTags(info.RegistrationID, tag)
}

// ----------------------------------------------------------------------------------------------------

func getRegistrationInfo(target UnityTarget) (*RegInfo, error) {
	info := &RegInfo{}

	m, err := common.NewMember().GetSingleBrief(target.MemberID)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("[JPush] Get RegistrationId | %v", err))
	}

	if len(m.DeviceTicket) > 0 && m.DeviceOnline == 1 {
		info.Param = UnityParams{
			MemberID:   m.ID,
			SubChannel: target.TargetID,
		}
		info.RegistrationID = m.DeviceTicket
		return info, nil
	}

	return info, fmt.Errorf("Not Found Device Ticket")
}
